/****************************************************************************
*                                                                           *
* Copyright (c) RSC. All rights reserved(2010).								*
* Developer: Marius Ionescu    						                        *
*                                                                           *
****************************************************************************/

using System;
using System.Collections;
using System.Data;
using System.Drawing;
using System.Web.Security;
using System.Web.UI.WebControls;
using NS_Controls;
using System.Web.Services;
using System.Web.Script.Services;
using System.Web.UI;
using AjaxControlToolkit;
using System.Web;
using System.Web.UI.HtmlControls;
using System.Collections.Generic;


public partial class Avioane : SessionPageBase
{
	private enum State { Null, Suggested, Accepted, Refused, InPlay, Changed, Finished }

	private class Storage
	{
		public class PlayerData
		{
			public int id;
			public string name;
			public bool GiP;
			public Pair gameKey;
			public bool onlineNow;
		}
		public class GameData
		{
			public int size, numberOfPlanes;
			public bool showPlanesWhenDead;
			public State gameState;
		}
		public Dictionary<string, int> players = new Dictionary<string, int>();
		public Dictionary<int, DateTime> lastPing = new Dictionary<int, DateTime>();
		public DateTime GetLastPing(int pId)
		{
			if ((lastPing != null) && (lastPing.ContainsKey(pId)))
				return lastPing[pId];
			return DateTime.MinValue;
		}
		public Dictionary<Pair, GameData> games = new Dictionary<Pair, GameData>();
		public override string ToString()
		{
			System.Text.StringBuilder dumpContext = new System.Text.StringBuilder();
			dumpContext.Append("Dumping of game data, "); dumpContext.Append(DateTime.Now.ToString("yyyy-MM-dd")); dumpContext.AppendLine();
			dumpContext.Append(players.Count); dumpContext.AppendLine();
			foreach (string player in players.Keys)
			{
				dumpContext.Append(players[player]);
				dumpContext.Append(' ');
				dumpContext.Append(player);
				dumpContext.AppendLine();
			}
			dumpContext.Append(games.Count); dumpContext.AppendLine();
			foreach (Pair opponents in games.Keys)
			{
				dumpContext.Append(opponents.First);
				dumpContext.Append(' ');
				dumpContext.Append(opponents.Second);
				dumpContext.Append(' ');
				GameData game = games[opponents];
				dumpContext.Append(game.size);
				dumpContext.Append(' ');
				dumpContext.Append(game.numberOfPlanes);
				dumpContext.Append(' ');
				dumpContext.Append(game.showPlanesWhenDead);
				dumpContext.Append(' ');
				dumpContext.Append(game.gameState);
				dumpContext.AppendLine();
			}
			return dumpContext.ToString();
		}
		public Storage() { }
		public Storage(string previousContext)
		{
			string[] lines = previousContext.Split(System.Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
			int offset = 1; //ignore lines[0] -- it only contains metadata
			if (lines.Length == offset)
				return; //previous version didn't override ToString... Context is void.
			int nPlayers = int.Parse(lines[offset++]);
			players = new Dictionary<string, int>(nPlayers);
			lastPing = new Dictionary<int, DateTime>(nPlayers);
			for (int p = 0; p < nPlayers; ++p)
			{
				int splitPoint = lines[offset + p].IndexOf(' ');
				int playerId = int.Parse(lines[offset + p].Substring(0, splitPoint));
				string playerName = lines[offset + p].Substring(splitPoint + 1);
				players[playerName] = playerId;
				lastPing[p] = DateTime.MinValue;
			}
			offset += nPlayers;
			int nGames = int.Parse(lines[offset++]);
			games = new Dictionary<Pair, GameData>(nGames);
			for (int g = 0; g < nGames; ++g)
			{
				/*
				int splitPoint = lines[offset + g].IndexOf(' ');
				int fPlayerId = int.Parse(lines[offset + g].Substring(0, splitPoint));
				int midPoint = lines[offset + g].IndexOf(' ', splitPoint + 1);
				int sPlayerId = int.Parse(lines[offset + g].Substring(splitPoint + 1, midPoint - splitPoint));
				Pair opponents = new Pair(fPlayerId, sPlayerId);
				games[opponents] = new GameData();
				splitPoint = lines[offset + g].IndexOf(' ', midPoint + 1);
				games[opponents].size = int.Parse(lines[offset + g].Substring(midPoint + 1, splitPoint - midPoint));
				//lines[offset + g].Substring(splitPoint + 1)
				*/
				string[] gameData = lines[offset + g].Split(' ');
				Pair opponents = new Pair(int.Parse(gameData[0]), int.Parse(gameData[1]));
				games[opponents] = new GameData() { size = int.Parse(gameData[2]), numberOfPlanes = int.Parse(gameData[3]), showPlanesWhenDead = bool.Parse(gameData[4]), gameState = (State)Enum.Parse(typeof(State), gameData[5]) };
			}
		}
	}

	protected void Page_Load(object sender, EventArgs e)
    {
		//TestMonthNames();
		try
        {
			SetupBoards();
            if (!IsPostBack)
            {
				AppStorage = null; //clean up objects, in case they were of an older (and incompatible) type...
                Initialize();
            }
			AppStorage.lastPing[AppStorage.players[PlayerID]] = DateTime.Now;
			RefreshLists();
        }
        catch (Exception ex)
        {
            this.SetMessage(ex.Message, true);
			output.Text = ex.ToString();
        }
    }

	private void TestMonthNames()
	{
		output.Text = "Culture property = '" + Culture + "'; ";
		output.Text += "Lang cookie = '" + Tools.GetLanguage(this.Request) + "'; ";
		System.Globalization.CultureInfo test = System.Globalization.CultureInfo.GetCultureInfo(Tools.GetLanguage(this.Request));
		output.Text += "Month count = " + test.DateTimeFormat.MonthNames.Length.ToString() + "; ";
		for (int monthIndex = 0; monthIndex < test.DateTimeFormat.MonthNames.Length; ++monthIndex)
			output.Text += monthIndex + " -&gt; " + test.DateTimeFormat.MonthNames[monthIndex] + ", ";
	}

	private void SetupBoards()
	{
		int nBoardSize = System.Convert.ToInt32(ddlBoardSize.SelectedValue);
		SetupBoard(tblMyBoard, nBoardSize);
		SetupBoard(tblEnemyBoard, nBoardSize);
	}
	private static System.Drawing.Color alternatedColour = System.Drawing.Color.FromArgb(240, 240, 240);
	private static Unit cellSize = new Unit(20.0, UnitType.Pixel);
	private void SetupBoard(Table target, int size)
	{
		target.BorderWidth = 1;
		target.Rows.Clear();
		for (int row = 0; row < size; ++row)
		{
			TableRow tr = new TableRow();
			target.Rows.Add(tr);
			for (int col = 0; col < size; ++col)
			{
				TableCell td = new TableCell();
				td.Width = cellSize;
				td.Height = cellSize;
				td.BackColor = ((row + col) % 2 == 0 ? System.Drawing.Color.White : alternatedColour);
				tr.Cells.Add(td);
				ImageButton clickable = new ImageButton();
				clickable.Click += new ImageClickEventHandler(clickable_Click);
				clickable.CommandArgument = target.ID + "@" + row + "," + col;
				clickable.ImageUrl = "~/Images/Hipocrate/spacer.gif"; //GetImageUrl();// 
				clickable.Height = cellSize;
				clickable.Width = cellSize;
				td.Controls.Add(clickable);
			}
		}
	}

	protected void clickable_Click(object sender, ImageClickEventArgs e)
	{
		messageSetup.Text = "clicked on " + (sender as ImageButton).CommandArgument;
	}

	private string PlayerID
	{
		get { return (ViewState["PlayerID"] ?? "").ToString(); }
		set { ViewState["PlayerID"] = value; }
	}

	private Storage AppStorage
	{
		get
		{
			if (Application["Avioanele"] == null)
				Application["Avioanele"] = new Storage();
			if (!(Application["Avioanele"] is Storage))
				throw new ApplicationException("Mismatched info: " + Application["Avioanele"].GetType().ToString());
			return (Application["Avioanele"] as Storage);
		}
		set
		{
			if (value != null)
				throw new ArgumentException("Cannot set AppStorage to a specific value...");
			if (Application["Avioanele"] == null)
				return;
			string previousVersion = Application["Avioanele"].ToString();
			if ((Application["Avioanele"] as Storage) == null)
				Application["Avioanele"] = new Storage(previousVersion);
		}
	}
	private Pair CurrentGameKey
	{
		get { return ViewState["CurrentGameKey"] as Pair; }
		set { ViewState["CurrentGameKey"] = value; }
	}

	private string ClientIp
	{
		get
		{
			messageEnemy.Text = Request.UserHostName + " @ " + Request.UserHostAddress + "<br/>" +
				Request.ServerVariables["REMOTE_ADDR"] + " / " + Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
			//NB: To get the IP address of the machine and not the proxy use: HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
			string clientIP = System.Net.Dns.Resolve(Request.UserHostName).HostName;
			//System.Net.Dns.GetHostEntry()
			if (clientIP.Equals("localhost") || clientIP.Equals("127.0.0.1"))
			{
				clientIP = System.Net.Dns.GetHostName();
				System.Net.IPAddress[] addresses = System.Net.Dns.Resolve(System.Net.Dns.GetHostName()).AddressList;
				string clientAddresses = "";
				foreach (System.Net.IPAddress address in addresses)
				    clientAddresses += address.ToString() + " ";
				//if (addresses.Length > 0)
				//	clientIP = addresses[0].ToString();
				//clientIP = System.Net.Dns.Resolve(clientIP).HostName;
			}
			return clientIP; //or: Request.UserHostName
		}
	}

	protected void Initialize()
    {
		PlayerID = ClientIp + "\\" + this.User.Identity.Name;
		messageSetup.Text = "You are: " + PlayerID;
		if (!AppStorage.players.ContainsKey(PlayerID))
			AppStorage.players.Add(PlayerID, AppStorage.players.Count);
		changeBoardSize(null, null);
	}
	private void RefreshLists()
	{
		ShowPlayers();
		ShowGames(AppStorage.players[PlayerID]);
	}

	private void ShowPlayers()
	{
		//e.g.: 192.168.1.122\user 127.0.0.1\user 192.168.1.12\user localhost\user devh2.rsc.local\user
		Storage.PlayerData[] ds = new Storage.PlayerData[AppStorage.players.Count];
		int pIndex = 0;
		foreach(string pKey in AppStorage.players.Keys)
		{
			int pId = AppStorage.players[pKey];
			ds[pIndex] = new Storage.PlayerData();
			ds[pIndex].id = pId;
			ds[pIndex].name = pKey;
			ds[pIndex].onlineNow = (AppStorage.GetLastPing(pId) > DateTime.Now.Subtract(new TimeSpan(0, 0, 30)));
			//TODO: also set ds[pIndex]. gameKey and GiP
			++pIndex;
		}
		rptPlayers.DataSource = ds;
		rptPlayers.DataBind();
	}

	protected void rptPlayers_ItemDataBound(object sender, RepeaterItemEventArgs e)
	{
		if ((e.Item.ItemType != ListItemType.Item) && (e.Item.ItemType != ListItemType.AlternatingItem)) return;
		if (!(e.Item.DataItem is Storage.PlayerData)) throw new ApplicationException("Unknown DataItem " + e.Item.DataItem.GetType().ToString());
		Storage.PlayerData pd = e.Item.DataItem as Storage.PlayerData;
		//string x = "";
		//foreach (Control c in e.Item.Controls)
		//    x += c.ID + " as " + c.GetType().ToString() + " ; ";
		//throw new ApplicationException(x + "pData = " + pd.Name);
		(e.Item.FindControl("name") as Literal).Text = pd.name;
		Label onlineNow = e.Item.FindControl("online") as Label;
		onlineNow.Text = pd.onlineNow.ToString();
		onlineNow.Font.Bold = pd.onlineNow;
		onlineNow.Font.Italic = !pd.onlineNow;
		onlineNow.ForeColor = pd.onlineNow ? System.Drawing.Color.Blue : System.Drawing.Color.Red;
		onlineNow.ToolTip = "Last seen: " + AppStorage.GetLastPing(pd.id).ToString("yyyy-MM-dd HH:mm:ss");
		if (!(pd.name.Equals(PlayerID)))
		{
			e.Item.FindControl("noGame").Visible = !pd.onlineNow;
			LinkButton link = e.Item.FindControl("link") as LinkButton;
			link.Visible = pd.onlineNow;
			if (pd.GiP)
			{
				object f = pd.gameKey.First;
				object match = (pd.id.Equals(f) ? pd.gameKey.Second : f);
				link.Text = "Yes. With " + match + ".";
				link.CommandArgument = pd.gameKey.First + "-" + pd.gameKey.Second;
			}
			else
			{
				link.CommandArgument = "-" + pd.id;
			}
		}
		else
		{
			e.Item.FindControl("link").Visible = false;
			(e.Item.FindControl("noGame") as Label).Text = "My own info...";
		}
	}

	protected void playerLink_Click(object sender, EventArgs e)
	{
		LinkButton source = sender as LinkButton;
		//messageEnemy.Text = "Clicked on playerLink #" + source.CommandArgument + ".";
		string playerId = source.CommandArgument;
		//create dummy game
		//set player flag
	}

	private void ShowGames(int playerID)
	{
		//TODO: list filtered AppStorage.games into rptGames
	}

	protected void changeBoardSize(object sender, EventArgs e)
	{
		int min = 1, max = 6, nBoardSize = System.Convert.ToInt32(ddlBoardSize.SelectedValue);
		if (nBoardSize < 11)
			max = 4;
		if (nBoardSize > 12)
			min = 3;
		string oldValue = ddlNPlanes.SelectedValue;
		ddlNPlanes.Items.Clear();
		for (int i = min; i <= max; ++i)
			ddlNPlanes.Items.Add(i.ToString());
		ddlNPlanes.SelectedValue = oldValue;
		SetupBoards();
	}

	protected void changeNPlanes(object sender, EventArgs e)
	{
		Pair game = CurrentGameKey;
		if (game != null)
		{
			if (AppStorage.games[game].gameState == State.Accepted)
			{
				//TODO: update numbers (planes still needing to be placed)
			}
		}
	}	
}
